package br.ufpb.di.ppgi.apresentacao.controllers;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import br.com.caelum.vraptor.Get;
import br.com.caelum.vraptor.Path;
import br.com.caelum.vraptor.Post;
import br.com.caelum.vraptor.Result;
import br.com.caelum.vraptor.Validator;
import br.com.caelum.vraptor.interceptor.download.Download;
import br.com.caelum.vraptor.interceptor.multipart.UploadedFile;
import br.com.caelum.vraptor.validator.Hibernate;
import br.com.caelum.vraptor.validator.ValidationMessage;
import br.com.caelum.vraptor.view.Results;
import br.com.simtecnologia.access.controll.annotation.ControlledResource;
import br.com.simtecnologia.access.controll.role.Roles;
import br.ufpb.di.ppgi.apresentacao.SiteConfiguration;
import br.ufpb.di.ppgi.negocio.ServiceLocator;
import br.ufpb.di.ppgi.negocio.iservicos.IDefesaService;
import br.ufpb.di.ppgi.negocio.modelo.defesa.Defesa;
import br.ufpb.di.ppgi.negocio.modelo.defesa.DefesaStatus;
import br.ufpb.di.ppgi.negocio.modelo.homologacao.defesa.HomologacaoDefesa;
import br.ufpb.di.ppgi.negocio.modelo.professorExterno.ProfessorExterno;
import br.ufpb.di.ppgi.negocio.modelo.proposta.Proposta;
import br.ufpb.di.ppgi.negocio.modelo.usuario.Usuario;
import br.ufpb.di.ppgi.negocio.modelo.usuario.UsuarioSessionInfo;
import br.ufpb.di.ppgi.persistencia.transaction.TransactionScoped;
import br.ufpb.di.ppgi.util.PdfUtil;

@Path("/admin/defesas/")
@ControlledResource
@Roles({"PROFESSOR"})
public class DefesasRestrictController extends AbstractController {
	
	private final IDefesaService servico;
	private final ServiceLocator serviceLocator;
    private final UsuarioSessionInfo usuarioInfo;
    private final SiteConfiguration conf;
    private final PdfUtil pdfUtil;
	

	public DefesasRestrictController(Result result, Validator validator,
			ServiceLocator services, UsuarioSessionInfo usuarioInfo, SiteConfiguration conf, PdfUtil pdfUtil) {
		super(result, validator, services);

		this.usuarioInfo = usuarioInfo;
		this.serviceLocator = services;
		this.servico = services.forDefesa();
		this.conf = conf;
		this.pdfUtil = pdfUtil;
	}
	
	@Get
	@Path("")
	public void index(String keyword, Integer page) {
		//TODO filtrar e paginar as propostas
		result.include("propostas", services.forProposta().listarByUsuarioId(usuarioInfo.getId()));
	}
	
	@Get
	@Path("solicitar-{id}")
	public void solicitar(Long id) {
		if(id != null) {
			List<Usuario> professores = serviceLocator.forUsuario().listarProfessores();
			professores.remove(usuarioInfo.getUsuario());
			
			Proposta proposta = serviceLocator.forProposta().buscar(id);
			result.include("proposta", proposta);
			result.include("defesa", servico.copiarDados(proposta));		
			result.include("aluno", proposta.getAluno());
			result.include("externos", serviceLocator.forProfessorExterno().listar());
			result.include("externo", null);
			result.include("professores", professores);
			result.include("professor3", null);
			result.include("professor4", null);
			result.include("professor5", null);
			result.include("professor6", null);
			result.include("professor7", null);
		}
	}
	
	@Post
	@Path("enviar")
	@TransactionScoped
	public void enviarDefesa(Defesa defesa, String hora, String minuto, UploadedFile anexo, Proposta proposta,
			Long professor3, Long professor4, Long professor5, Long professor6, Long professor7, Long externo) {
		if (defesa == null) {
			validator.add(new ValidationMessage("Escolha uma defesa.", "erro"));
			validator.onErrorUse(Results.logic()).redirectTo(ProcessosRestrictController.class).index(null);
			return;
		}

		//Inserindo os professores a mais, além dos dois obrigatórios
		List<Usuario> professores = new ArrayList<Usuario>();
		if(professor3 != null) {
			Usuario prof3 = services.forUsuario().buscar(professor3);
			if(prof3 != null)
				professores.add(prof3);
		}
		if(professor4 != null) {
			Usuario prof4 = services.forUsuario().buscar(professor4);
			if(prof4 != null)
				professores.add(prof4);
		}
		if(professor5 != null) {
			Usuario prof5 = services.forUsuario().buscar(professor5);
			if(prof5 != null)
				professores.add(prof5);
		}
		if(professor6 != null) {
			Usuario prof6 = services.forUsuario().buscar(professor6);
			if(prof6 != null)
				professores.add(prof6);
		}
		if(professor7 != null) {
			Usuario prof7 = services.forUsuario().buscar(professor7);
			if(prof7 != null)
				professores.add(prof7);
		}
		defesa.setProfessores(professores);
		
		//Inserindo professor externo
		List<ProfessorExterno> profExternos = new ArrayList<ProfessorExterno>();
		if(externo != null) {
			ProfessorExterno profExt = services.forProfessorExterno().buscar(externo);
			if(profExt != null)
				profExternos.add(profExt);
		}
		defesa.setProfExternos(profExternos);
		
		defesa.updateHoraMinuto(Integer.valueOf(hora),Integer.valueOf(minuto));
		
		Date dataDefesa = defesa.getData_defesa();
		if (dataDefesa.before(new Date())){
			validator.add(new ValidationMessage("Nao é possível agendar uma defesa para uma data no passado.", "erro"));
			validator.onErrorUse(Results.page()).of(getClass()).solicitar(proposta.getId());
			return;
		}
		
		defesa.saveAnexo(anexo, conf.getAnexosDirPath());
		
		validator.addAll(Hibernate.validate(defesa));
		validator.onErrorUse(Results.page()).of(ProcessosRestrictController.class).index(null);
		
		if (defesa.getId() != null)
			servico.atualizar(defesa);
		else {
			servico.adicionar(defesa);
			services.forProposta().finalizar(proposta);
		}
		
		result.redirectTo(ProcessosRestrictController.class).index("Defesa de dissertação encaminhada para homologação.");
	}
	
	@Path("pdf/{id}")
	@Roles({"COLEGIADO"})
	public Download pdf(Long id) {
		Defesa defesa = services.forDefesa().buscar(id);
		return pdfUtil.downloadPdf(defesa.getFile_path(), id+".pdf");
	}
	
	@Path("{id}")
	@Roles({"COLEGIADO","SECRETARIO"})
	public void detalhes(Long id) {
		Defesa defesa = services.forDefesa().buscar(id);
		
		result.include("defesa", defesa);
	}
	
	@Path("{homologacao.pk.defesa.id}/homologar-{homologado}")
	@Roles({"COLEGIADO"})
	@TransactionScoped
	public void homologar(HomologacaoDefesa homologacao, Boolean homologado) {
		Defesa defesa = homologacao.getPk().getDefesa();
		
		homologacao.getPk().setColegiado(usuarioInfo.getUsuario());
		
		homologado = services.forDefesa().homologar(homologacao,homologado);
		
		defesa = servico.buscar(defesa.getId());
		if(defesa.getStatus() == DefesaStatus.HOMOLOGACAO_REPROVADA)
			services.forProposta().reativarByAlunoId(defesa.getAluno().getId());
		
		result.include("homologado",homologado);
		result.redirectTo(PendenciasRestrictController.class).index();
	}
	
//	@Path("acompanhamento")
//	@Roles({"COORDENADOR"})
//	public void acompanhamento() {
//		result.include("defesas",servico.listar());
//	}
	
	@Path("{defesa.id}/aprovar-{aprovado}")
	@Roles({"COORDENADOR"})
	@TransactionScoped
	public void aprovar(Defesa defesa, Boolean aprovado) {
		try {
			aprovado = services.forDefesa().aprovar(defesa,aprovado);
			
			if(!aprovado)
				services.forProposta().reativarByAlunoId(defesa.getAluno().getId());
			
			result.include("aprovado_defesa",aprovado);
			result.redirectTo(AcompanhamentosRestrictController.class).index();
		} catch (Exception e) {
			result.include("aprovado_defesa",false);
			validator.add(new ValidationMessage("Defesa nao homologada", "error"));
			validator.onErrorUse(Results.logic()).redirectTo(AcompanhamentosRestrictController.class).index();
		}
	}	
	
}